package com.tensai.study.java.features.JDK8.date;

import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 1、所有的日期类都是可变的，因此他们都不是线程安全的，
 * 这是Java日期类最大的问题之一
 * <p>
 * 2、Java的日期/时间类的定义并不一致，在java.util和java.sql的包中都有日期类，
 * 此外用于格式化和解析的类在java.text包中定义
 * <p>
 * 3、java.util.Date同时包含日期和时间，而java.sql.Date仅包含日期，将其纳入java.sql包并不合理。
 * 另外这两个类都有相同的名字，这本身就是一个非常糟糕的设计。对于时间、时间戳、格式化以及解析，并没有一些明确定义的类。
 * 对于格式化和解析的需求，我们有java.text.DateFormat抽象类，但通常情况下，SimpleDateFormat类被用于此类需求
 * <p>
 * 4、日期类并不提供国际化，没有时区支持，
 * 因此Java引入了java.util.Calendar和java.util.TimeZone类，
 * 但他们同样存在上述所有的问题
 * <p>
 * <p>
 * 1、不变性：新的日期/时间API中，所有的类都是不可变的，这对多线程环境有好处。
 * <p>
 * 2、关注点分离：新的API将人可读的日期时间和机器时间（unix timestamp）明确分离，
 * 它为日期（Date）、时间（Time）、日期时间（DateTime）、时间戳（unix timestamp）以及时区定义了不同的类。
 * <p>
 * 3、清晰：在所有的类中，方法都被明确定义用以完成相同的行为。举个例子，要拿到当前实例我们可以使用now()方法，
 * 在所有的类中都定义了format()和parse()方法，而不是像以前那样专门有一个独立的类。
 * 为了更好的处理问题，所有的类都使用了工厂模式和策略模式，一旦你使用了其中某个类的方法，与其他类协同工作并不困难。
 * <p>
 * 4、实用操作：所有新的日期/时间API类都实现了一系列方法用以完成通用的任务，
 * 如：加、减、格式化、解析、从日期/时间中提取单独部分，等等。
 * <p>
 * 5、可扩展性：新的日期/时间API是工作在ISO-8601日历系统上的，但我们也可以将其应用在非IOS的日历上。
 */
public class DateTest {

    /**
     * 属性 	        含义
     * Instant 	        代表的是时间戳
     * LocalDate 	    代表日期，比如2020-01-14
     * LocalTime 	    代表时刻，比如12:59:59
     * LocalDateTime    代表具体时间 2020-01-12 12:22:26
     * ZonedDateTime    代表一个包含时区的完整的日期时间，偏移量是以UTC/  格林威治时间为基准的
     * Period 	        代表时间段
     * ZoneOffset 	    代表时区偏移量，比如：+8:00
     * Clock 	        代表时钟，比如获取目前美国纽约的时间
     * 获取当前时间
     */
    @Test
    public void t1() {
        //获取当前时间戳
        Instant instant = Instant.now();
        //获取当前日期
        LocalDate localDate = LocalDate.now();
        //获取当前时刻
        LocalTime localTime = LocalTime.now();
        //获取当前具体时间
        LocalDateTime localDateTime = LocalDateTime.now();
        //获取带有时区的时间
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
    }

    /**
     * 字符串转换
     */
    @Test
    public void t2() {
//        jdk8：
        String str = "2019-01-11";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(str, formatter);

//        jdk7:
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = simpleDateFormat.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    /**
     * Date转换LocalDate
     */
    @Test
    public void t3() {
        Date date = new Date();
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();

        // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime。
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        System.out.println("Date = " + date);
        System.out.println("LocalDate = " + localDate);
        System.out.println("LocalDateTime = " + localDateTime);
    }

    /**
     * LocalDate转Date
     */
    @Test
    public void t4() {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = LocalDate.now();
        ZonedDateTime zdt = localDate.atStartOfDay(zoneId);

        Date date = Date.from(zdt.toInstant());

        System.out.println("LocalDate = " + localDate);
        System.out.println("Date = " + date);
    }

    /**
     * 时间戳转LocalDateTime
     */
    @Test
    public void t5() {
        long timestamp = System.currentTimeMillis();

        Instant instant = Instant.ofEpochMilli(timestamp);

        LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转时间戳
     */
    @Test
    public void t6() {
        LocalDateTime dateTime = LocalDateTime.now();

        dateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();

        dateTime.toInstant(ZoneOffset.of("+08:00")).toEpochMilli();

        dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
}
